//
//  main.m
//  08-iOS新特性
//
//  Created by dllo on 16/7/13.
//  Copyright © 2016年 daming. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "Person.h"
#import "Truck.h"
#import "Student.h"
#import "Truck.h"
int main(int argc, const char * argv[]) {
#pragma mark - Nullability(判断是否为空的能力)
    Person *per = [[Person alloc] init];
    
    // nonnull 修饰的属性对应的getter和setter
    NSString *objc = nil;
    per.name = objc;
    [per setName:objc];
    per.name = @"张三";
    [per name];
    
    // nullable 修饰的属性, 对应的getter和setter方法
//    per setSex:<#(NSString * _Nullable)#>;
//    [per sex];
    per.sex = nil;
    
    //null_resettable
    [per setFriends:nil];
    [per friends];
#pragma mark - 泛型
    // 带泛型的容器(规定了容器中所存储的类型)
    // 带泛型的数组
    // 声明一个可变数组, 内部存放的都是NSString
    // 1.数组中添加其他的类型会有警告
    // 2.数组取出来的类型不再是id类型, 对应变成声明时类型
    // 3.泛型会改变类的一些方法, 使与声明的类型相同
    NSMutableArray<NSString *> *array = [NSMutableArray arrayWithObjects:@"123", nil];
    NSMutableArray *array1 = [NSMutableArray array];
//    NSInteger a = array.firstObject.length;
    [array addObject:@""];
//    [array addObject:<#(nonnull NSString *)#>];
//    [array1 addObject:<#(nonnull id)#>];
    NSInteger count = [array objectAtIndex:0].length;
    
    // 带泛型的字典
    NSMutableDictionary<NSString *, NSString *> *dic =[NSMutableDictionary dictionaryWithObjectsAndKeys:@"张三", @"name", nil];
//    [dic objectForKey:<#(nonnull NSString *)#>]
    NSInteger c = [dic objectForKey:@"name"].length;
    
    // 自定义泛型
    Truck<Person *> *truckPer = [[Truck alloc] init];
    [truckPer addObject:per];
    
    Student *stu = [[Student alloc] init];
    stu.stuNumber = @"15545";
    [truckPer addObject:stu];
    Truck<Student *> *truckStu = [[Truck alloc] init];
    [truckStu addObject:stu];
    [truckPer addObject:per];
    [truckPer addObject:stu];
    // 协变性 与 逆变性
    Truck *truck = nil;
    Truck<NSArray *> *truck1 = nil;
    Truck<NSMutableArray *> *truck2 = nil;
    // 大类型(任意类型) 可以给有泛型的赋值
    // 也可以有泛型的给它赋值
    truck = truck1;
    truck = truck2;
    truck1 = truck;
    truck2 = truck;
    
    // __covariant 协变性: 子类在给父类赋值时, 自动强转
    // Truck<NSArray *> 与 Truck<NSMutableArray *>
    truck1 = truck2;
    // __contravariant 逆变性: 父类型可以强制转换成子类型
    truck2 = truck1;
    
#pragma mark - __kindof
    // __kindof一般用在方法的返回值
    // 加__kindof修饰后返回的类型及其子类型, 都可以接收这个返回值
    Truck *truckKindOf = [[Truck alloc] init];
    NSMutableArray *arr = [truckKindOf returnArray];
    NSArray *arr1 = [truckKindOf returnArray];
    

    
    
    
    
    
    
    
    
        return 0;
}
